﻿using Models;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Utils
{
    /// <summary>
    /// Http上传下载文件
    /// </summary>
    public class HttpUtil
    {
        #region HttpDownloadFile 下载文件
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url">下载文件url路径</param>
        /// <param name="cookie">cookie</param>
        public static MemoryStream HttpDownloadFile(string url, CookieContainer cookie = null, WebHeaderCollection headers = null)
        {
            try
            {
                // 设置参数
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                request.Method = "GET";
                request.CookieContainer = cookie;

                if (headers != null)
                {
                    foreach (string key in headers.Keys)
                    {
                        request.Headers.Add(key, headers[key]);
                    }
                }

                //发送请求并获取相应回应数据
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                Stream responseStream = response.GetResponseStream();

                //创建写入流
                MemoryStream stream = new MemoryStream();

                byte[] bArr = new byte[10240];
                int size = responseStream.Read(bArr, 0, (int)bArr.Length);
                while (size > 0)
                {
                    stream.Write(bArr, 0, size);
                    size = responseStream.Read(bArr, 0, (int)bArr.Length);
                }
                stream.Seek(0, SeekOrigin.Begin);
                responseStream.Close();

                return stream;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region HttpDownloadFile 下载文件(异步)
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url">下载文件url路径</param>
        /// <param name="cookie">cookie</param>
        public static async Task<MemoryStream> HttpDownloadFileAsync(string url, CookieContainer cookie = null, WebHeaderCollection headers = null)
        {
            try
            {
                // 设置参数
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                request.Method = "GET";
                request.CookieContainer = cookie;

                if (headers != null)
                {
                    foreach (string key in headers.Keys)
                    {
                        request.Headers.Add(key, headers[key]);
                    }
                }

                //发送请求并获取相应回应数据
                HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                Stream responseStream = response.GetResponseStream();

                //创建写入流
                MemoryStream stream = new MemoryStream();

                byte[] bArr = new byte[10240];
                int size = await responseStream.ReadAsync(bArr, 0, (int)bArr.Length);
                while (size > 0)
                {
                    stream.Write(bArr, 0, size);
                    size = await responseStream.ReadAsync(bArr, 0, (int)bArr.Length);
                }
                stream.Seek(0, SeekOrigin.Begin);
                responseStream.Close();

                return stream;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region HttpDownloadFile 下载文件(基于回调的异步)
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url">下载文件url路径</param>
        /// <param name="cookie">cookie</param>
        public static void HttpDownloadFileAsyncWithCallback(string url, HttpUtilAsyncState state = null, Action<object> callback = null, CookieContainer cookie = null, WebHeaderCollection headers = null)
        {
            try
            {
                if (state.State == 0)
                {
                    // 设置参数
                    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                    request.Method = "GET";
                    request.CookieContainer = cookie;

                    if (headers != null)
                    {
                        foreach (string key in headers.Keys)
                        {
                            request.Headers.Add(key, headers[key]);
                        }
                    }

                    //发送请求并获取相应回应数据
                    request.BeginGetResponse(asyncResult =>
                    {
                        HttpUtilAsyncState asyncState = asyncResult.AsyncState as HttpUtilAsyncState;

                        try
                        {
                            HttpWebResponse response = request.EndGetResponse(asyncResult) as HttpWebResponse;
                            asyncState.ResponseStream = response.GetResponseStream();

                            HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
                        }
                        catch (Exception ex)
                        {
                            asyncState.Exception = ex;
                            asyncState.State = 2;
                            HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
                        }
                    }, new HttpUtilAsyncState { Request = request, State = 1 });
                    return;
                }

                if (state.State == 1)
                {
                    byte[] bArr = new byte[10240];
                    state.ResponseStream.BeginRead(bArr, 0, (int)bArr.Length, asyncResult =>
                    {
                        HttpUtilAsyncState asyncState = asyncResult.AsyncState as HttpUtilAsyncState;

                        try
                        {
                            int size = state.ResponseStream.EndRead(asyncResult);
                            if (size > 0)
                            {
                                state.Stream.Write(bArr, 0, size);

                                HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
                            }
                            else
                            {
                                asyncState.State = 2;
                                HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
                            }
                        }
                        catch (Exception ex)
                        {
                            asyncState.Exception = ex;
                            asyncState.State = 2;
                            HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
                        }
                    }, state);
                    return;
                }

                if (state.State == 2)
                {
                    if (state.Exception != null)
                    {
                        callback(state.Exception);
                        return;
                    }
                    else
                    {
                        state.Stream.Seek(0, SeekOrigin.Begin);
                        state.ResponseStream.Close();
                        callback(state.Stream);
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

    }

}
